home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / libs / libelf-0.5 / libelf-0 / libelf-0.5.2 / nlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-19  |  3.9 KB  |  171 lines

  1. /*
  2. nlist.c - implementation of the nlist(3) function.
  3. Copyright (C) 1995 Michael Riepe <riepe@ifwsn4.ifw.uni-hannover.de>
  4.  
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9.  
  10. This library is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. Library General Public License for more details.
  14.  
  15. You should have received a copy of the GNU Library General Public
  16. License along with this library; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19.  
  20. #include <private.h>
  21. #include <nlist.h>
  22. #include <fcntl.h>
  23.  
  24. struct hash {
  25.     const char* name;
  26.     unsigned long   hash;
  27.     Elf32_Sym*    sym;
  28. };
  29.  
  30. static int
  31. _elf_nlist(Elf *elf, struct nlist *nl) {
  32.     Elf_Scn *symtab = NULL;
  33.     Elf_Scn *strtab = NULL;
  34.     Elf_Data *symdata;
  35.     Elf_Data *strdata;
  36.     Elf32_Ehdr *ehdr;
  37.     Elf32_Shdr *shdr;
  38.     Elf_Scn *scn;
  39.     Elf32_Sym *symbols;
  40.     const char *strings;
  41.     unsigned nsymbols;
  42.     unsigned nstrings;
  43.     unsigned i;
  44.     const char *name;
  45.     struct hash *table;
  46.     unsigned nhash;
  47.     unsigned long hash;
  48.     unsigned long j;
  49.  
  50.     if (!(ehdr = elf32_getehdr(elf))) {
  51.     return -1;
  52.     }
  53.     scn = NULL;
  54.     while ((scn = elf_nextscn(elf, scn))) {
  55.     if (!(shdr = elf32_getshdr(scn))) {
  56.         return -1;
  57.     }
  58.     if (shdr->sh_type == SHT_SYMTAB) {
  59.         strtab = elf_getscn(elf, shdr->sh_link);
  60.         symtab = scn;
  61.         break;
  62.     }
  63.     if (shdr->sh_type == SHT_DYNSYM) {
  64.         strtab = elf_getscn(elf, shdr->sh_link);
  65.         symtab = scn;
  66.     }
  67.     }
  68.     if (elf_errno()) {
  69.     return -1;
  70.     }
  71.     symdata = elf_getdata(symtab, NULL);
  72.     strdata = elf_getdata(strtab, NULL);
  73.     if (!symdata || !strdata) {
  74.     return -1;
  75.     }
  76.     symbols = (Elf32_Sym*)symdata->d_buf;
  77.     strings = (const char*)strdata->d_buf;
  78.     nsymbols = symdata->d_size / sizeof(Elf32_Sym);
  79.     nstrings = strdata->d_size;
  80.     if (!symbols || !strings || !nsymbols || !nstrings) {
  81.     return -1;
  82.     }
  83.  
  84.     /*
  85.      * build a simple hash table
  86.      */
  87.     nhash = 3 * nsymbols - 4;
  88.     if (!(table = (struct hash*)malloc(nhash * sizeof(*table)))) {
  89.     return -1;
  90.     }
  91.     for (i = 0; i < nhash; i++) {
  92.     table[i].name = NULL;
  93.     }
  94.     for (i = 1; i < nsymbols; i++) {
  95.     if (symbols[i].st_name < 0 && symbols[i].st_name >= nstrings) {
  96.         free(table);
  97.         return -1;
  98.     }
  99.     if (symbols[i].st_name == 0) {
  100.         continue;
  101.     }
  102.     name = strings + symbols[i].st_name;
  103.     hash = elf_hash(name);
  104.     for (j = hash; table[j %= nhash].name; j += 3) {
  105.         if (table[j].hash != hash) {
  106.         continue;
  107.         }
  108.         if (table[j].name == name || !strcmp(table[j].name, name)) {
  109.         break;
  110.         }
  111.     }
  112.     table[j].hash = hash;
  113.     table[j].name = name;
  114.     table[j].sym = &symbols[i];
  115.     }
  116.  
  117.     /*
  118.      * symbol lookup
  119.      */
  120.     for (i = 0; (name = nl[i].n_name) && *name; i++) {
  121.     hash = elf_hash(name);
  122.     for (j = hash; table[j %= nhash].name; j += 3) {
  123.         if (table[j].hash == hash && !strcmp(table[j].name, name)) {
  124.         break;
  125.         }
  126.     }
  127.     if (table[j].name) {
  128.         nl[i].n_value = table[j].sym->st_value;
  129.         nl[i].n_scnum = table[j].sym->st_shndx;
  130.     }
  131.     else {
  132.         nl[i].n_value = 0;
  133.         nl[i].n_scnum = 0;
  134.     }
  135.     /*
  136.      * this needs more work
  137.      */
  138.     nl[i].n_type = 0;
  139.     nl[i].n_sclass = 0;
  140.     nl[i].n_numaux = 0;
  141.     }
  142.     free(table);
  143.     return 0;
  144. }
  145.  
  146. int
  147. nlist(const char *filename, struct nlist *nl) {
  148.     int result = -1;
  149.     unsigned oldver;
  150.     Elf *elf;
  151.     int fd;
  152.  
  153.     if ((oldver = elf_version(EV_CURRENT)) != EV_NONE) {
  154.     if ((fd = open(filename, O_RDONLY)) != -1) {
  155.         if ((elf = elf_begin(fd, ELF_C_READ, NULL))) {
  156.         result = _elf_nlist(elf, nl);
  157.         elf_end(elf);
  158.         }
  159.         close(fd);
  160.     }
  161.     elf_version(oldver);
  162.     }
  163.     if (result) {
  164.     while (nl->n_name && *nl->n_name) {
  165.         nl->n_value = 0;
  166.         nl++;
  167.     }
  168.     }
  169.     return result;
  170. }
  171.